package com.zengchen.user.task;/**
 * @program: user
 * @description: CurrentPoemJob
 * @author: zengchen
 * @create: 2019-11-10 17:07
 **/

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zengchen.content.common.PoemOT;
import com.zengchen.user.entity.CurrentPoem;
import com.zengchen.user.entity.ReciteHis;
import com.zengchen.user.feignclient.ContentCenterFeignClient;
import com.zengchen.user.service.CurrentPoemService;
import com.zengchen.user.service.ReciteHisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @program: user
 * @description: CurrentPoemJob
 * @author: zengchen
 * @create: 2019-11-10 17:07
 **/
@Component
@Slf4j
public class CurrentPoemTask {

    @Autowired
    private CurrentPoemService currentPoemService;

    @Autowired
    private ReciteHisService reciteHisService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private ContentCenterFeignClient contentCenterFeignClient;

    // 每天凌晨1点0分0秒时执行
    @Scheduled(cron = "0 0 1 * * *")
    public void updateCrtPoemEveryday() {
        // 利用redis存值是否成功来判断多台部署user-center时，重复执行task
        boolean isTaskDown = stringRedisTemplate.opsForValue().setIfAbsent("CurrentPoemTask", "CurrentPoemTask", 50, TimeUnit.SECONDS);
        log.info("updateCrtPoemEveryday start with isTaskDown = {}", isTaskDown);
        // true，set值成功，任务还未被其它实例执行，分批更新数据，每批100条数据，避免记录太多撑爆内存
        if (isTaskDown) {
            int loopCount = 1; // 循环查询次数
            long size = 100; //  每次查询100条
            List<PoemOT> allPoem = contentCenterFeignClient.getAllPoem();
            while (true) {
                log.info("第 {} 次循环 .......", loopCount);
                Page<CurrentPoem> page = new Page<>();
                page.setCurrent(1); // 每次都应该查询第一页
                page.setSize(size);
                IPage<CurrentPoem> currentPage = currentPoemService.page(page, new QueryWrapper<CurrentPoem>()
                        .lt("update_date", LocalDate.now())
                );
                List<CurrentPoem> beforeList = currentPage.getRecords();
                if (CollectionUtils.isEmpty(beforeList)) { // 已经没有数据了
                    log.info("已经没有未处理数据，跳出循环 .......");
                    break; // 跳出循环
                }
                log.info("当前查出未处理数据 {} 条 .......", beforeList.size());
                // 从未背诵过的诗词里随机发放新诗词
                List<CurrentPoem> afterList = beforeList.stream().peek(e -> {
                    List<ReciteHis> reciteHisList = reciteHisService.list(new QueryWrapper<ReciteHis>().eq("member_id", e.getMemberId()));
                    List<Integer> reciteIds = reciteHisList.stream().map(ReciteHis::getPoemId).collect(Collectors.toList());
                    List<Integer> remainList = allPoem.stream().filter(p -> !reciteIds.contains(p.getId())).map(PoemOT::getId).collect(Collectors.toList());
                    if(!CollectionUtils.isEmpty(remainList)){ // 剩余诗词不为空
                        // 随机取出一首诗词id
                        Integer poemId = (remainList.size() == 1) ? remainList.get(0) : remainList.get(ThreadLocalRandom.current().nextInt(remainList.size()-1));
                        e.setPoemId(poemId);
                        e.setUpdateDate(LocalDate.now());
                    }
                }).collect(Collectors.toList());
                log.info("更新数据 {} 条 .......", afterList.size());
                currentPoemService.saveOrUpdateBatch(afterList);
                loopCount++;
            }
        }
        log.info("updateCrtPoemEveryday end ");
    }

}
